//
//  InstallationDetailViewController.swift
//  ezyform
//
//  Created by MoennigQ on 09/12/2016.
//  Copyright © 2016 Client.Solution Pty Ltd. All rights reserved.
//

import UIKit
import Alamofire
import HandyJSON
import SwiftyJSON
import CoreLocation
import RealReachability
import MBProgressHUD
import Photos
import PhotosUI
import YJLocationConverter

class InstallationDetailViewController: BaseViewController {
    var skipToWhere: SkipToWhere? //打开Detail跳转到那个模块
    @IBOutlet weak var loadJobDetailFaildView: InstallationDetailLoadFaildView!
    @IBOutlet weak var jobDetailBackView: UIView!
    @IBOutlet weak var checkListView: InstallationDetailTabCheckListView!
    
    @IBOutlet weak var signatureView: InstallationDetailTabSignaturesView!
    
    @IBOutlet weak var detailView: InstallationDetailTabDetail!
    
    var pvd_id: String = ""
    var model = PVDDetailModel()
    var currentCheckListModel: PVDChecklistModel = PVDChecklistModel()
    
    @IBOutlet weak var topBarView: InstallationDetailTopBar!
    
    @IBOutlet weak var reuploadView: InstallationDetailReuploadView!
    @IBOutlet weak var reuploadViewHeightContrains: NSLayoutConstraint!
    var checklistArray = [PVDChecklistModelForReupload]()
    var panelNumberArray = [PanelNumberImageDBModel]()
    var signatureArray = [SignatureImageDBModel]()
    var uploadedCnt = 0
    var totalCnt: Int = 0
    //panel number
    var panelNumbersTotal: Int = 0
    var panelNumbersPages: Int = 0
    var currentPage: Int = 1
    //current tab value
    var currentTabBtn: UIButton?
    //
    var hub: MBProgressHUD?
    var delegate: RefreshReuploadInfoFromDetailDelegate?
    var hideReuploadViewDelegate: HideDetailReuploadViewDelegate?
    var currentListModel: InstallationListModel?
    var devationLocation: LocationModel = LocationModel()
    var panelInstalledLcation: LocationModel = LocationModel() //点击panel installed时定位到的当前位置信息
    var panelInstalledLatitudeKey: String = ""
    var panelInstalledLongitudeKey: String = ""
    var panelInstalledDateOfCompletionKey: String = ""
    var panelInstalledDateOfCompletion: String = ""
    let checklistCellHeight: Int = 60
    override func viewDidLoad() {
        super.viewDidLoad()
        //reupload view
        //
        NotificationCenter.default.addObserver(self, selector: #selector(checkLocalInfoToSetReuploadInfo), name: NSNotification.Name(rawValue: "refreshDetailReuploadView"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(hideReuploadViewNotification(_:)), name: NSNotification.Name(rawValue: "hideReuploadView"), object: nil)
        //checklist image上传完后，刷新checklist
        NotificationCenter.default.addObserver(self, selector: #selector(refreshChecklistImages(_:)), name: NSNotification.Name(rawValue: "refreshChecklistImages"), object: nil)
        //监听checklist tableview的高度
        self.checkListView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.detailView.attachmentView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.detailView.panelInfoView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.detailView.inverterInfoView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.detailView.batteryInfoView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)

        reuploadView.reuploadClosure = { [weak self] in
            guard let strongSelf = self else {return}
            if Connectivity.isConnectedToInternet, let pvdId = strongSelf.model.pvd_id {
                let vc = InstallationDetailReuploadViewController()
                strongSelf.definesPresentationContext = true
                vc.reuploadDataType = "3"
                vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
                //required when
                vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
                vc.installtionIds = [pvdId]
                vc.refreshClosure = { (uploadAllDataSuccessFlag) in
                    strongSelf.loadData(true)

                }
                strongSelf.navigationController?.present(vc, animated: true, completion: nil)
            }else{
                strongSelf.showFailureInfo()
            }
        }
        detailView.tag = 1
        detailView.panelInfoView.editPanelBtnClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editPanelInfo(strongSelf.model,vc: strongSelf)
        }
        detailView.inverterInfoView.editInverterBtnClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editInverterInfo(strongSelf.model,vc: strongSelf)
        }
        detailView.batteryInfoView.editBatteryBtnClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editBatteryInfo(strongSelf.model,vc: strongSelf)
        }
        detailView.phoneBtnClickClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().callOwnerPhone(strongSelf.model)
        }
        detailView.copyAddrBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().copyOwnerAddress(strongSelf.model.install_address?.installation_address ?? "",parentView: strongSelf.view)
        }
        detailView.pickupAddressView.copyAddrBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().copyOwnerAddress(strongSelf.model.delivery_address?.map_full_address ?? "",parentView: strongSelf.view)
        }
        detailView.editOwnerNameBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editOwnerInfo(strongSelf.model,vc: strongSelf)
        }
        detailView.addressBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            let addressModel = DeliveryAddressModel()
            let latitude = strongSelf.model.install_address?.location?.latitude
            let longitude = strongSelf.model.install_address?.location?.longitude
            addressModel.latitude = latitude == nil ? "" : "\(latitude!)"
            addressModel.longitude = longitude == nil ? "" : "\(latitude!)"
            addressModel.street_number = strongSelf.model.install_address?.street_number ?? ""
            addressModel.street_name = strongSelf.model.install_address?.street_name ?? ""
            addressModel.street_type = strongSelf.model.install_address?.street_type ?? ""
            addressModel.suburb = strongSelf.model.install_address?.suburb ?? ""
            addressModel.state = strongSelf.model.install_address?.state ?? ""
            addressModel.post_code = strongSelf.model.install_address?.post_code ?? ""
            MapNavigationHelper.shared.showMapsOptions(addressModel,vc: strongSelf)
        }
        detailView.pickupAddressView.addressBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            let addressModel = DeliveryAddressModel()
            let latitude = strongSelf.model.delivery_address?.latitude
            let longitude = strongSelf.model.delivery_address?.longitude
            addressModel.latitude = latitude == nil ? "" : "\(latitude!)"
            addressModel.longitude = longitude == nil ? "" : "\(latitude!)"
            addressModel.street_number = strongSelf.model.delivery_address?.street_number ?? ""
            addressModel.street_name = strongSelf.model.delivery_address?.street_name ?? ""
            addressModel.street_type = strongSelf.model.delivery_address?.street_type ?? ""
            addressModel.suburb = strongSelf.model.delivery_address?.suburb ?? ""
            addressModel.state = strongSelf.model.delivery_address?.state ?? ""
            addressModel.post_code = strongSelf.model.delivery_address?.post_code ?? ""
            MapNavigationHelper.shared.showMapsOptions(addressModel,vc: strongSelf)
        }
        detailView.attachmentView.openAttachmentClosure = { [weak self](attachmentType,attachmentModel) in
            guard let strongSelf = self else {return}
            guard let url = attachmentModel.url else {
                return
            }
            let vc = AttachmentViewController()
            vc.attchmentType = .PVDDetailAttachment
            vc.attachmentURL = url
            vc.attachmentTitle = attachmentType
            strongSelf.navigationController?.pushViewController(vc, animated: false)
        }
        detailView.editInstallationAddressBtn.addTarget(self, action: #selector(editInstallationAddressBtnClick), for: UIControl.Event.touchUpInside)
        detailView.attachmentView.nocUploadFooterView.uploadFileClosure = {[weak self] in
            guard let strongSelf = self else {return}
            let vc = UIDocumentPickerViewController(documentTypes: ["com.adobe.pdf"], in: UIDocumentPickerMode.import)
            vc.delegate = strongSelf
            vc.modalPresentationStyle = .overFullScreen
            strongSelf.navigationController?.present(vc, animated: true, completion: nil)
        }
        detailView.attachmentView.nocUploadFooterView.uploadPhotoClosure = {[weak self] in
            guard let strongSelf = self else {return}
            let alertController = UIAlertController(title: NSLocalizedString("ChooseOption", comment: ""), message: nil, preferredStyle: .actionSheet)
            let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)

            let library = UIAlertAction(title: NSLocalizedString("Photolibrary", comment: ""), style: .default, handler: {  action in
                strongSelf.selectFromPhotosLibrary()
            })
            let takePhoto = UIAlertAction(title: NSLocalizedString("TakePhoto", comment: ""), style: .default, handler: { action in
                AVCaptureDevice.requestAccess(for: AVMediaType.video) { (status) in
                    DispatchQueue.main.async {
                        if status {
                            let vc = NOCTakePhotoViewController()
                            vc.confirmClosure = {[weak self] (originalImage) in
                                guard let strongSelf = self else {return}
                                strongSelf.uploadAttachment(originalImage)
                            }
                            vc.modalPresentationStyle = .fullScreen
                            strongSelf.present(vc, animated: true, completion: nil)
                        }else{
                            strongSelf.alertViewWithMsg(message: NSLocalizedString("camera.permission", comment: ""))
                        }
                    }

                }
            })
            alertController.addAction(cancel)
            alertController.addAction(takePhoto)
            alertController.addAction(library)

            if Tool.getCurrentDeviceType() == APPConfig.iPadType {
                alertController.modalPresentationStyle = UIModalPresentationStyle.popover

                if let popPresenter:UIPopoverPresentationController = alertController.popoverPresentationController {
                    popPresenter.sourceView = strongSelf.detailView.attachmentView.nocUploadFooterView.uploadPhotoBtn
                    popPresenter.sourceRect = strongSelf.detailView.attachmentView.nocUploadFooterView.uploadPhotoBtn.bounds
                    strongSelf.present(alertController, animated: true, completion: nil)
                }

            }else{
                strongSelf.present(alertController, animated: true, completion: {})
            }

        }
        checkListView.tableView.toDERRegisterClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.toDERRegister()
        }
        checkListView.tableView.toPanelListClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.toPanelNumersVC()

        }
        checkListView.tableView.toInverterListClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.toInverterNumberVC()

        }
        checkListView.tableView.toCallPhoneClosure = {
            InstallationDetailVCHelper.shared().callPhone(APPConfig.SupportPhone)
        }
        checkListView.tableView.toSendEmailClosure = {
            InstallationDetailVCHelper.shared().sendEmail(APPConfig.SupportEmail)
        }
        //checklist
        checkListView.tableView.toImageListClosure = { [weak self] (currentIndex) in
            guard let strongSelf = self else {return}
            strongSelf.toImageListVC(currentIndex)
        }
        checkListView.tableView.toEditTextClosure = { [weak self](checklistModel) in
            guard let strongSelf = self else {return}
            strongSelf.showEditCheckListText(checklistModel)
        }
        checkListView.tableView.toPanelInstallClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.getDetailBeforePanelInstalled()
        }
        checkListView.tableView.toClickChecklitBoolItemClosure = { [weak self] (serverModel, index) in
            guard let strongSelf = self else {return}
            strongSelf.toClickBoolItemOfChecklist(serverModel,index: index)
        }
        checkListView.startJobBtn.addTarget(self, action: #selector(startJob), for: UIControl.Event.touchUpInside)
        checkListView.finishJobBtn.addTarget(self, action: #selector(finishJob), for: UIControl.Event.touchUpInside)
        //
        signatureView.startOrFinishJobClosure = {[weak self](operation) in
            guard let strongSelf = self else {return}
            if operation == OperateJobStatus.StartJob {
                strongSelf.startJob()
            }else if operation == OperateJobStatus.FinishJob {
                strongSelf.finishJob()
            }
        }
        signatureView.signatureListView.toSignatureClosure = { [weak self](type) in
            guard let strongSelf = self else {return}
            InstallationSignatureService().setDataInfo(strongSelf, model: strongSelf.model).toSignature(type)
        }
        signatureView.signatureListView.toEditOwnerInfoClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editOwnerInfo(strongSelf.model,vc: strongSelf)
        }
        detailView.systemInfoView.editInstallationTypeBtnClosure = {[weak self] in
            guard let strongSelf = self else {return}
            if strongSelf.model.canEditPVDDetailFlag {
                InstallationDetailVCHelper.shared().editInstallationType(strongSelf.model,vc: strongSelf)
            }
        }
        detailView.systemInfoView.editBatteryBtnClosure = {[weak self] in
            guard let strongSelf = self else {return}
            if strongSelf.model.canEditPVDDetailFlag {
                InstallationDetailVCHelper.shared().editBatteryInfo(strongSelf.model,vc: strongSelf)
            }
        }
        detailView.systemInfoView.editGridConnectdClosure = {[weak self] in
            guard let strongSelf = self else {return}
            if strongSelf.model.canEditPVDDetailFlag {
                InstallationDetailVCHelper.shared().editGridConnectdInfo(strongSelf.model,vc: strongSelf)
            }
        }
        detailView.systemInfoView.spvTipBtn.addTarget(self, action: #selector(spvTipBtnClick), for: UIControl.Event.touchUpInside)
        //
        topBarView.detailBtn.addTarget(self, action: #selector(selectedType(_:)), for: UIControl.Event.touchUpInside)
        topBarView.checkListBtn.addTarget(self, action: #selector(selectedType(_:)), for: UIControl.Event.touchUpInside)
        topBarView.signaturesBtn.addTarget(self, action: #selector(selectedType(_:)), for: UIControl.Event.touchUpInside)
        //由于网络原因加载失败显示loadJobDetailFaildView，job detail全部不显示
        self.loadJobDetailFaildView.retryBtn.addTarget(self, action: #selector(refreshJobDetail), for: UIControl.Event.touchUpInside)
        self.currentTabBtn = topBarView.detailBtn
        self.detailView.isHidden = true

        self.refreshJobDetail()
    }
    func toPanelNumersVC(_ animate: Bool = true) {
        if let jobStatus = self.model.job_status, jobStatus != "0" {
            let vc = PVDPanelNumberViewController()
            //print(model.pvd_id)
            vc.model = self.model
            vc.delegate = self
            vc.hideDetailReuploadViewDelegate = self
            vc.title = self.model.gwt_id
            vc.hidesBottomBarWhenPushed = true
            self.navigationController?.pushViewController(vc, animated: animate)
        }
        
    }
    func toInverterNumberVC(_ animate: Bool = true) {
        if let jobStatus = self.model.job_status, jobStatus != "0" {
            let vc = PVDInverterNumberViewController()
            //print(model.pvd_id)
            vc.model = self.model
            vc.delegate = self
            vc.hideDetailReuploadViewDelegate = self
            vc.title = self.model.gwt_id
            vc.hidesBottomBarWhenPushed = true
            self.navigationController?.pushViewController(vc, animated: animate)
        }
    }
    @objc func refreshChecklistImages(_ notification: NSNotification){
        self.cacheLoadData()
    }
    //notloadingFlag is false by default for first loading and refresh data
    //showFaildFlag is true for refresh job data
    @objc func loadData(_ notLoadingFlag: Bool, showFaildFlag: Bool = false,checkIfNeedResignFlag: Bool = false)
    {
        let vm = PVDDetailViewModel()
        //set block
        vm.setBlockAfterNetwork({ (result) -> Void in
            self.resetUIAfterLoad(true,showLoadFaildViewFlag: false)
            
            if !notLoadingFlag {
                Tool.shared.hideLoadingView()
            }
            if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                self.model.copyAllValuesOfModel(data)
                if self.title?.count == 0 {
                    self.title = self.model.gwt_id
                }
            }
            self.dealDataAfterLoadData()
            if let msg = self.model.re_sign_statement_message, checkIfNeedResignFlag && msg != "" && Connectivity.isConnectedToInternet {//true表示需要检查是否有重新签名的提示信息
                self.alertViewWithMsg(message: msg) {
                    self.readResignStatementMsg()
                }
            }
        }) { (code, error) -> Void in
            if !notLoadingFlag {
                Tool.shared.hideLoadingView()
            }
            self.setRefeshBtn()
            if error == RequestErrorType.NetworkError.rawValue{
                self.resetUIAfterLoad(false,showLoadFaildViewFlag: true)
                if showFaildFlag {
                    self.showFailureInfo()
                }
            }else{
                self.resetUIAfterLoad(false,showLoadFaildViewFlag: false)
                self.showErrorInfo(code, error)
            }
        }
        if !notLoadingFlag {
            Tool.shared.showLoadingView()
        }
        
        vm.getInstallationsDetail()
        
    }
    @objc func selectFromPhotosLibrary(){
        if #available(iOS 14, *) {//iOS 14之后的相册选择（包括14）
            let level = PHAccessLevel.readWrite
            PHPhotoLibrary.requestAuthorization(for: level){ [weak self](status) in
                guard let strongSelf = self else {return}
                DispatchQueue.main.async {
                    if status == .authorized {//全部相片
                        var configuration = PHPickerConfiguration()
                        configuration.filter = .images
                        configuration.selectionLimit = 1//最多选择1个
                        let picker = PHPickerViewController(configuration: configuration)
                        picker.delegate = strongSelf
                        picker.modalPresentationStyle = .overFullScreen
                        strongSelf.present(picker, animated: true)
                    }else if status == .limited{//部分相片
                        strongSelf.selectFromPhotosLibraryBefore()
                    }else {//无权限
                        strongSelf.alertViewWithMsg(message: NSLocalizedString("photos.permission", comment: ""))
                        return
                    }
                }
            }
        }else{//14以前的
            PHPhotoLibrary.requestAuthorization({ [weak self](status) in
                guard let strongSelf = self else {return}
                DispatchQueue.main.async {
                    if status == .authorized {//有权限
                        strongSelf.selectFromPhotosLibraryBefore()
                    }else{//无权限
                        strongSelf.alertViewWithMsg(message: NSLocalizedString("photos.permission", comment: ""))
                        return
                    }
                }
            })
        }
    }
    //iOS 14之前的相册选择（不包括14）
    fileprivate func selectFromPhotosLibraryBefore(){
        _ = self.presentHGImagePicker(maxSelected: 1) { [weak self](assets) in
            guard let strongSelf = self else {return}
            if assets.count > 0 {
                for i in 0  ..< assets.count {
                    if let originImage = Tool.shared.getUIImage(asset: assets[i]) {
                        strongSelf.uploadAttachment(originImage)
                    }
                }
            }
        }
    }
    func uploadAttachment(_ resultImage: UIImage){
        let attachmentData = Tool.shared.resetSizeOfImageData(source_image: resultImage)
        Tool.shared.showLoadingView()
        let vm = PVDDetailViewModel()
        vm.setBlockAfterNetwork({ (result) -> Void in
            Tool.shared.hideLoadingView()
            if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                self.model.copyAllValuesOfModel(data)
                self.detailView.attachmentView.tableView.reloadData()
            }
            self.alertViewWithMsg(message: "Upload success")
        }) { (code,msg) -> Void in
            Tool.shared.hideLoadingView()
            self.alertViewWithMsg(message: msg)
        }
        vm.uploadAttachment(attachmentData)
    }
    func toImageListVC(_ index: Int){
        guard index < self.model.pvd_checklists.count else {
            return
        }
        //如果当前checklist是mid-installation check-up或者testing and commissioning checklist而且上一步没有完成
        let serverModel = self.model.pvd_checklists[index]
        let checklistID = serverModel.id ?? 0
        if (checklistID == ChecklistFixedId.midInstall.rawValue || checklistID == ChecklistFixedId.testAndCommission.rawValue) && serverModel.preChecklistDone == false{
            let alertMsg = "Please take '\(serverModel.preChecklistTitle)'"
            self.alertViewWithMsg("Temporary Locked",message: alertMsg,cancelBtnStr: "Dismiss")
        }else{
            self.forwardToImageListVC(index)
        }
        
    }
    private func forwardToImageListVC(_ index: Int){
        let vc =  InstallationImageListViewController()
        vc.model = self.model
        vc.delegate = self
        vc.currentCheckListModel = self.model.pvd_checklists[index]
        vc.hideDetailReuploadViewDelegate = self
        self.navigationController?.pushViewController(vc,animated: false)
    }
    @objc func refreshJobDetail(){//此方法用在refresh和retry,这两个地方需要检查是否有重新签名的提示，不做它用
        //每次都重新拿下Accreditation Number，用于判断当前用户是否是Installer
        Tool.shared.showLoadingView()
        SystemInfoService.shared().loadMyInformation {[weak self] in
            guard let strongSelf = self else {return}
            Tool.shared.hideLoadingView()
            strongSelf.loadData(false, showFaildFlag: true,checkIfNeedResignFlag: true)
        } faildClosure: {[weak self](code,err) in
            guard let strongSelf = self else {return}
            Tool.shared.hideLoadingView()
            strongSelf.resetUIAfterLoad(false,showLoadFaildViewFlag: true)
            strongSelf.setRefeshBtn()
            strongSelf.showErrorInfo(code,err)
        }
    }
    //loadSuccessFlag: true加载成功
    func resetUIAfterLoad(_ loadSuccessFlag: Bool,showLoadFaildViewFlag: Bool = false){
        if loadSuccessFlag {
            self.topBarView.isHidden = false
            self.jobDetailBackView.isHidden = false
            self.loadJobDetailFaildView.isHidden = true
            if let btn = self.currentTabBtn{
                self.selectedType(btn)
            }
        }else{
            self.topBarView.isHidden = true
            self.jobDetailBackView.isHidden = true
            self.loadJobDetailFaildView.isHidden = !showLoadFaildViewFlag
            self.hideReuploadView()
        }
    }
    
    fileprivate func dealDataAfterLoadData(){
        
        self.checkJobStatus()
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
        //
        self.detailView.setData(model: self.model)
        self.checkListView.tableView.refreshData(self.model)
        
        self.panelInstalledLatitudeKey = "\(String(describing: self.model.pvd_id))" + "Latitude"
        self.panelInstalledLongitudeKey = "\(String(describing: self.model.pvd_id))" + "Longitude"
        self.panelInstalledDateOfCompletionKey = "\(String(describing: self.model.pvd_id))" + "DateOfCompletion"
        //如果panel installed了，将缓存到本地的date of completion 清除掉
        if let spvCheck = self.model.spv_check, let spvInstalled = self.model.spv_installed, spvCheck && spvInstalled {
            UserDefaults.standard.removeObject(forKey: self.panelInstalledDateOfCompletionKey)
        }
        //先用本地数据设置
        self.getLocalErrorHistory()
        //检查有没有消息通知
        self.checkJobMsg()
        //是否跳转到对应的tab 页面，跳转完成后置空
        if let toWhere = self.skipToWhere {
            switch toWhere {
            case .Panel,.Inverter, .Checklist:
                self.selectedType(self.topBarView.checkListBtn)
                
                if toWhere == .Inverter{
                    self.toInverterNumberVC()
                }else if toWhere == .Panel{
                    self.toPanelNumersVC()
                }
            case .Signature:
                self.selectedType(self.topBarView.signaturesBtn)
            }
            self.skipToWhere = nil
        }
    }
    func readResignStatementMsg(){
        let vm = PVDDetailViewModel()
        vm.setBlockAfterNetwork { result in
            if let data = result as? PVDDetailModel{
                self.model.re_sign_statement_message = data.re_sign_statement_message
            }
        } errorBlock: { _,_ in
            
        }
        vm.readResignStatementMsg()
    }
    @objc func checkLocalInfoToSetReuploadInfo(){
        if Connectivity.isConnectedToInternet && GlobalOperationQueue.operations.count > 0{
            self.hideReuploadView()
        }else {//有任何本地数据，要显示Reupload
            if self.model.checkListModifyFlag || self.model.panelNumbersModifyFlag || self.model.inverterNumbersModifyFlag || self.model.signaturesModifyFlag{
                self.reuploadView.setReuploadInfo(true)
                self.reuploadViewHeightContrains.constant = 50
            }else{
                self.hideReuploadView()
            }
        }
    }
    @objc func hideReuploadView(){
        self.reuploadView.setReuploadInfo(false)
        self.reuploadViewHeightContrains.constant = 0
    }
    @objc func hideReuploadViewNotification(_ notification: NSNotification){
        self.hideReuploadView()
    }
    func setRefeshBtn(){
        let btn1 = UIButton(type: .custom)
        btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 24)
        btn1.setImage(UIImage(named: "installation_detail_refresh_icon"), for: .normal)
        btn1.addTarget(self, action: #selector(refreshJobDetail), for: .touchUpInside)
        let item1 = UIBarButtonItem(customView: btn1)
        
        self.navigationItem.setRightBarButtonItems([item1], animated: true)
    }
    func loadDataAndToContinue(_ toContinueType: String)
        {
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                
                self.resetUIAfterLoad(true)
                Tool.shared.hideLoadingView()
                if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                    self.model.copyAllValuesOfModel(data)
                }
                
                self.checkJobStatus()
                //检查是否有本地数据，有的话显示Reupload btn
                self.checkLocalInfoToSetReuploadInfo()
                
                self.detailView.setData(model: self.model)
                self.checkListView.tableView.refreshData(self.model)
                
                self.panelInstalledLatitudeKey = "\(String(describing: self.model.pvd_id))" + "Latitude"
                self.panelInstalledLongitudeKey = "\(String(describing: self.model.pvd_id))" + "Longitude"
                self.panelInstalledDateOfCompletionKey = "\(String(describing: self.model.pvd_id))" + "DateOfCompletion"
                //如果panel installed了，将缓存到本地的date of completion 清除掉
                if let spvCheck = self.model.spv_check, let spvInstalled = self.model.spv_installed, spvCheck && spvInstalled {
                    UserDefaults.standard.removeObject(forKey: self.panelInstalledDateOfCompletionKey)
                }
                //本地数据上传完毕后
                if  toContinueType == "1" {//continue finish job
                    self.finishJob()
                }else if toContinueType == "2"{//continue panel installed
                    self.checkSPVPanelInstalledAfterUploadLocalData()
                }
            }) { (code, error) -> Void in
                if error == RequestErrorType.NetworkError.rawValue{
                    self.resetUIAfterLoad(true)
                }else{
                    self.resetUIAfterLoad(true,showLoadFaildViewFlag: true)
                }
                
                self.setRefeshBtn()
                Tool.shared.hideLoadingView()
                self.showErrorInfo(code, error)
            }
            //add Loading view
            if toContinueType == "1" {//finish job
                Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.finishJob", comment: ""))
            }else if toContinueType == "2" {//panel installed
                Tool.shared.showLoadingView("Checking...")
            }
            vm.getInstallationsDetail()
            
        }
    @objc
    func editInstallationAddressBtnClick(){
        let vc =  EditJobDetailViewController()
        vc.model = self.model
        vc.delegate = self
        self.navigationController?.pushViewController(vc,animated: false)
    }
    @objc
    func getPanelNumberForSpv(){
        if Connectivity.isConnectedToInternet {
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                Tool.shared.hideLoadingView()
                
                if let list = JSONDeserializer<PanelNumberImageDBModel>.deserializeModelArrayFrom(json: result as? String) as? Array<PanelNumberImageDBModel>{
                    self.model.pvd_serial_numbers = list
                    
                    self.getLocalPanelNumbers()
                }
                
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.showErrorInfo(code, error)
                
            }
            //add Loading view
            Tool.shared.showLoadingView()
            vm.getPanelNumberListForSpv()
        }else{
            self.showFailureInfo()
        }
        
    }
    
    //only for cache request data
    @objc func cacheLoadData(_ loadingText:String = "" , closure:(()->Void)? = nil)
    {
        let vm = PVDDetailViewModel()
        //set block
        vm.setBlockAfterNetwork({ (result) -> Void in
            if loadingText != ""{
                Tool.shared.hideLoadingView()
            }
            if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                self.model.copyAllValuesOfModel(data)
                self.dealDataAfterLoadData()
                closure?()
            }
            
        }) { (code, error) -> Void in
            if loadingText != ""{
                Tool.shared.hideLoadingView()
            }
            self.alertViewWithMsg(message: error)
        }
        if loadingText != ""{
            Tool.shared.showLoadingView(loadingText)
        }
        vm.getInstallationsDetail()
    }
    @objc func spvTipBtnClick(){
        let vc = SPVTipViewController()
        self.definesPresentationContext = true
        vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
        vc.parentVC = self
        //required when
        vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
        self.navigationController?.present(vc, animated: true, completion: nil)
    }
    @objc func reopenJob(){
        let vm = PVDDetailViewModel()
        vm.setBlockAfterNetwork({ (result) -> Void in
            Tool.shared.hideLoadingView()
            //缓存Job Status状态数据
            DispatchQueue.main.async {
                self.cacheLoadData()
            }
            if let data = result as? PVDDetailModel{
                self.model.copyAllValuesOfModel(data)
                self.dealDataAfterLoadData()
                if let _ = self.currentListModel{
                    self.currentListModel!.status = "Installing"
                }
            }
            self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.reopenedJob", comment: ""))
        }) {(code, error) -> Void in
            Tool.shared.hideLoadingView()
            self.showErrorInfo(code, error)
            
        }
        //add Loading view
        Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.reopenJob", comment: ""))
        vm.reopenJob()
    }
    @objc func startJob(){
        if !Connectivity.isConnectedToInternet {
            self.showFailureInfo()
            return
        }
        self.requestStartJob(APPConfig.currentLocation.combineStr)
        
    }
    func requestStartJob(_ locationStr: String = ""){
        if Connectivity.isConnectedToInternet {
            let vm = PVDDetailViewModel()
            vm.setBlockAfterNetwork({(result) -> Void in
                
                Tool.shared.hideLoadingView()
                //缓存Job Status状态数据
                DispatchQueue.main.async {
                    self.cacheLoadData()
                }
                if let data = result as? PVDDetailModel{
                    self.model.copyAllValuesOfModel(data)
                    self.dealDataAfterLoadData()
                    if let _ = self.currentListModel{
                        self.currentListModel!.status = "Installing"
                    }
                }
                
                self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.startedJob", comment: ""))
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.showErrorInfo(code, error)
            }
            //add Loading view
            Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.startJob", comment: ""))
            vm.startJob(locationStr)
        }else{
            self.showFailureInfo()
        }
        
    }
    @objc func finishJob(){
        if !Connectivity.isConnectedToInternet {
            self.showFailureInfo()
            return
        }
        
        //local data need to upload before finish job
        if self.model.checkListModifyFlag ||  self.model.signaturesModifyFlag || self.model.panelNumbersModifyFlag || self.model.inverterNumbersModifyFlag{
            self.alertViewWithUpload(message: NSLocalizedString("pvd.detail.localdata.check.uploaded", comment: ""),toContinueType: "1")//"1": to finish job
        }else{
            self.cacheLoadData(NSLocalizedString("pvd.detail.finishJob", comment: "")) {
                self.requestFinishJobAPI(APPConfig.currentLocation.combineStr)
            }
        }
    }
    
    func requestFinishJobAPI(_ loactionStr: String = ""){
        if Connectivity.isConnectedToInternet {
            //校验checklit，signatures，panel numbers所有的必填项
            if InstallationDetailVCHelper.shared().checkRequiredWhenFinishJob(self.model ,vc: self) {
                let vm = PVDDetailViewModel()
                vm.setBlockAfterNetwork({ (result) -> Void in
                    Tool.shared.hideLoadingView()
                    //必须缓存Job status的数据，防止无网络刷新数据又显示finish job的问题
                    DispatchQueue.main.async {
                        self.cacheLoadData()
                    }
                    if let data = result as? PVDDetailModel{
                        self.model.copyAllValuesOfModel(data)
                        self.dealDataAfterLoadData()
                        if let _ = self.currentListModel{
                            self.currentListModel!.status = "Installed"
                        }
                    }
                    
                    if self.model.der_register {
                        self.alertViewWithDER()
                    }else{
                        self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.finishedJob", comment: "")){
                            if let data = self.model.installer_rating_id{
                                self.toAPPCommnt(data)
                            }
                        }
                    }
                    
                }) {(code, error) -> Void in
                    Tool.shared.hideLoadingView()
                    self.showErrorInfoFormat(code,error)
                }
                //add Loading view
                Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.finishJob", comment: ""))
                vm.finishJob(loactionStr)
            }
            
            
        }else{
            self.showFailureInfo()
        }
        
    }
    //APP评分
    func toAPPCommnt(_ rateId: Int){
        guard let tabBarVC = self.tabBarController else{
            return
        }
        let view = AppCommentView()
        view.submitClosure = { [weak self] (model) in
            guard let strongSelf = self else {return}
            
            model.id = rateId
            let vm = PVDDetailViewModel()
            vm.setBlockAfterNetwork { result in
                if model.ignoreFlag == false{//submit时才显示submitting
                    Tool.shared.hideLoadingView()
                }
                view.removeFromSuperview()
            } errorBlock: { _, errMsg in
                if model.ignoreFlag == false{//submit时才显示submitting
                    Tool.shared.hideLoadingView()
                    strongSelf.alertViewWithMsg(message: errMsg)
                }
            }
            //add Loading view
            if model.ignoreFlag == false{//submit时才显示submitting
                Tool.shared.showLoadingView(NSLocalizedString("Submitting...", comment: ""))
            }
            vm.submitAPPComment(model)
        }
        tabBarVC.view.addSubview(view)
        view.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    //finish job的时候如果有本地数据，弹出框中增加upload的button
    func alertViewWithUpload(_ title : String = "", message : String,cancelBtnStr: String = "Cancel", textAlignment: NSTextAlignment = .center, toContinueType: String){
        let alertViewController = UIAlertController(title: title, message: "", preferredStyle: UIAlertController.Style.alert)
        
        let cancelAction = UIAlertAction(title: cancelBtnStr, style: .cancel,handler: nil)
        
        let uploadAction = UIAlertAction(title: "Upload&Continue", style: .default){(action) -> Void in
            self.uploadAllLocalData(toContinueType)
        }
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = textAlignment
        let messageText = NSMutableAttributedString(
            string: message,
            attributes: [
                NSAttributedString.Key.paragraphStyle: paragraphStyle,
                NSAttributedString.Key.font: UIFont(name: "Arial", size: 13) as Any,
                NSAttributedString.Key.foregroundColor: UIColor.black
            ]
        )
        
        alertViewController.setValue(messageText, forKey: "attributedMessage")
        
        alertViewController.addAction(cancelAction)
        alertViewController.addAction(uploadAction)
        self.present(alertViewController, animated: true, completion: nil)
        
    }
    func uploadAllLocalData(_ toContinueType: String){
        guard let pvdId = self.model.pvd_id else {
            return
        }
        if Connectivity.isConnectedToInternet {
            //2.进行数据上传
            let vc = InstallationDetailReuploadViewController()
            self.definesPresentationContext = true
            vc.reuploadDataType = toContinueType
            vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
            //required when
            vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
            vc.installtionIds = [pvdId]
            vc.refreshClosure = { [weak self](uploadAllDataSuccessFlag) in
                guard let strongSelf = self else {return}
                if uploadAllDataSuccessFlag {//上传成功继续下边的步骤
                    strongSelf.loadDataAndToContinue(toContinueType)
                }else{//上传不成功刷新数据
                    strongSelf.cacheLoadData()
                }
                
            }
            self.navigationController?.present(vc, animated: true, completion: nil)
        }else{
            self.showFailureInfo()
        }
    }
    @objc
    func toDERRegister(){
        if self.model.isInstallerFlag {//当前用户是installer才能操作DER Register
            let vc = DERRegisterViewController()
            if let gwtID = self.model.gwt_id {
                vc.gwtID = gwtID
            }
            self.navigationController?.pushViewController(vc, animated: false)
        }
    }
    func alertViewWithDER(){
        let vc = FinishJobAlertViewController()
        vc.toDERRegistClose = {
            self.toDERRegister()
        }
        //需要弹出App评分功能
        if let data = self.model.installer_rating_id{
            vc.okClosure = {[weak self] in
                guard let strongSelf = self else {return}
                strongSelf.toAPPCommnt(data)
            }
        }
        
        self.definesPresentationContext = true
        vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
        //required when
        vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
        self.navigationController?.present(vc, animated: true, completion: nil)
    }
    
    @objc func selectedType(_ sender: UIButton){
        self.currentTabBtn = sender
        let value = sender.tag
        
        if value == 0 {//detail
            detailView.isHidden = false
            signatureView.isHidden = true
            checkListView.isHidden = true
            
        }else if value == 1{//checklist
            checkListView.isHidden = false
            detailView.isHidden = true
            signatureView.isHidden = true
            
            
        }else if value == 2{//signature
            detailView.isHidden = true
            signatureView.isHidden = false
            checkListView.isHidden = true
        }
        self.topBarView.changeImage(value)
    }
    //refreshFlag表示重新拿到本地数据收，是否需要重新刷新tableview（只有删除的时候是false不需要刷新）
    func getLocalPanelNumbers(){
        InstallationDetailVCHelper.shared().getLocalPanelNumbers(self.model)
    }
    //refreshFlag表示重新拿到本地数据收，是否需要重新刷新tableview（只有删除的时候是false不需要刷新）
    func getLocalInverterNumbers(){
        InstallationDetailVCHelper.shared().getLocalInverterNumbers(self.model)
    }
    func checkJobMsg(){
        //installer才检查
        if self.model.isInstallerFlag{
            //先把有的按钮显示出来,等有网络请求完再刷新
            let vm = SystemViewModel()
            vm.setBlockAfterNetwork { (result) in
                if let dic = result as? NSArray{
                    if let data = try? JSONSerialization.data(withJSONObject: dic, options: []){
                        do{
                            let list = try JSONDecoder().decode([JobNotReadModel].self, from: data)
                            if list.count > 0{
                                let notReadModel = list[0]
                                if let newMsgCnt = notReadModel.new_message_count,newMsgCnt > 0{//服务器上有未读数据，则拉取
                                    self.getNewJobMsg()
                                }else{//服务器上没有新数据，则使用本地数据
                                    self.getLocalErrorHistory()
                                }
                            }
                        }catch {//原因是Json中的数据类型和Model中的数据类型不一致导致的
                            print("JobErrorModel convert JSON data to model failed")
                        }
                    }
                }
            } errorBlock: { (_,_) in
                self.getLocalErrorHistory()
            }
            vm.getErrorNotRead()
        }else{
            self.refreshNavigationBarItems()
        }
        
    }
    func getNewJobMsg(){
        let vm = SystemViewModel()
        vm.setBlockAfterNetwork { (result) in
            if let dic = result as? NSArray{
                if let data = try? JSONSerialization.data(withJSONObject: dic, options: []){
                    do{
                        let list = try JSONDecoder().decode([JobErrorModel].self, from: data)
                        if list.count > 0{
                            for model in list{
                                DBManager.shared.insertJobErrorHistory(model)
                            }
                        }
                        //
                        self.getLocalErrorHistory()
                    }catch {//原因是Json中的数据类型和Model中的数据类型不一致导致的
                        print("JobErrorModel convert JSON data to model failed")
                    }
                }
            }
        } errorBlock: { _,_ in
            self.getLocalErrorHistory()
        }
        vm.getErrorHistories()
    }
    func getLocalErrorHistory(){
        let notReadFlag = DBManager.shared.checkJobErrorHistoryNotRead()
        self.refreshNavigationBarItems(notReadFlag)
    }
    func refreshNavigationBarItems(_ haveNewFlag: Bool = false){
        let jobStatus = self.model.job_status
        if self.model.isInstallerFlag {//installer才能reopen或finish job
            var items: [UIBarButtonItem] = [UIBarButtonItem]()
            //refresh
            let btn1 = UIButton(type: .custom)
            btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 24)
            btn1.setImage(UIImage(named: "installation_detail_refresh_icon"), for: .normal)
            btn1.addTarget(self, action: #selector(refreshJobDetail), for: .touchUpInside)
            let item1 = UIBarButtonItem(customView: btn1)
            items.append(item1)
            //reopen
            if jobStatus == "2" {
                //reopen
                let btn = UIButton(type: .custom)
                btn.frame = CGRect(x: 0, y: 0, width: 30, height: 24)
                btn.setImage(UIImage(named: "installation_detail_reopen_icon"), for: .normal)
                btn.addTarget(self, action: #selector(reopenJob), for: .touchUpInside)
                let item = UIBarButtonItem(customView: btn)
                items.append(item)
            }
            //job msg
            let msgBtn = UIButton(type: .custom)
            msgBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 24)
            var iconName = "installation_detail_jobmsg_icon"
            if haveNewFlag {//有未读msg
                iconName = "installation_detail_jobmsg_newmsg_icon"
            }
            msgBtn.setImage(UIImage(named: iconName ), for: .normal)
            msgBtn.addTarget(self, action: #selector(toJobMessage), for: .touchUpInside)
            let msgItem = UIBarButtonItem(customView: msgBtn)
            items.append(msgItem)
            
            self.navigationItem.setRightBarButtonItems(items, animated: true)
        }else{//当前用户是designer只能刷新
            self.setRefeshBtn()
        }
    }
    @objc func toJobMessage(){
        let vc = JobErrorHistoriesViewController()
        vc.delegate = self
        vc.gwtId = self.model.gwt_id ?? ""
        self.navigationController?.pushViewController(vc, animated: false)
    }
    func checkJobStatus(){
        self.signatureView.updateUIByJobStatus(self.model)
        self.checkListView.updateUIByJobStatus(self.model)
        if let tabBtn = self.currentTabBtn{
            self.selectedType(tabBtn)
        }
        //检查是否有msg，再设置导航栏按钮
        self.checkJobMsg()
    }
    //upload checklist without uploading view
    func uploadCheckListWithoutImage(_ indexPath: IndexPath){
        if !Connectivity.isConnectedToInternet {
            //检查是否有本地数据，有的话显示Reupload btn
            self.checkLocalInfoToSetReuploadInfo()
            return
        }
        
        if self.model.checkListModifyFlag {
            //隐藏Detail的ReuploadView
            self.hideReuploadView()
            
            let group = DispatchGroup()
            for checklistModel in self.model.localChecklists {
                if checklistModel.type != "image" {//text and boolean
                    
                    group.enter()
                    DBManager.shared.setUpoadingFlag(checklist_table_name,keyId: checklistModel.dbId!, flag: "1")
                    GlobalOperationQueue.addOperation {
                        let vm = PVDDetailViewModel()
                        
                        vm.setBlockAfterNetwork({ (result) -> Void in
                            DBManager.shared.deleteChecklsitData(pvdId: self.model.id,checklistId: checklistModel.id!)
                            
                            self.model.pvd_checklists = (JSONDeserializer<PVDChecklistModel>.deserializeModelArrayFrom(json: result as? String) as? Array<PVDChecklistModel>)!
                            
                            group.leave()
                            
                        }, errorBlock: { (code, error) -> Void in
                            DBManager.shared.setUpoadingFlag(checklist_table_name,keyId: checklistModel.dbId!, flag: "0")
                            group.leave()
                            
                        })
                        
                        vm.uploadChecklistDataWithoutImages(self.model,checklistId: checklistModel.id!)
                    }
                }
            }
            group.notify(queue: DispatchQueue.main) {
                InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
                //检查是否有本地数据，有的话显示Reupload btn
                self.checkLocalInfoToSetReuploadInfo()
                //要刷新整个表格，因为Checklist Group 布局要刷新required和optional的完成数量
                self.checkListView.tableView.refreshData(self.model)//reloadRows(at: [indexPath], with: UITableView.RowAnimation.none)
                self.checkJobMsg()
            }
        }
        
    }
    //异步上传Checklist数据
    func uploadCheckListAsync(){
        if !Connectivity.isConnectedToInternet {
            //检查是否有本地数据，有的话显示Reupload btn
            self.checkLocalInfoToSetReuploadInfo()
            return
        }
        
        if self.model.checkListModifyFlag {
            //隐藏Detail的ReuploadView
            self.hideReuploadView()
            
            let group = DispatchGroup()
            let semaphore = DispatchSemaphore(value: 1)
            for checklistModel in self.model.localChecklists {
                if checklistModel.type == "image" {
                    //1.local add images
                    let localAddImages = checklistModel.localAddImages
                    for imageModel in localAddImages {
                        group.enter()
                        DBManager.shared.setUpoadingFlag(checklistImage_table_name,keyId: imageModel.dbId!, flag: "1")
                        
                        GlobalOperationQueue.addOperation {
                            let checklistVM = PVDDetailViewModel()
                            checklistVM.setBlockAfterNetwork({ (result) -> Void in
                                
                                DBManager.shared.deleteChecklistImageData(model: imageModel)
                                
                                self.model.pvd_checklists = (JSONDeserializer<PVDChecklistModel>.deserializeModelArrayFrom(json: result as? String) as? Array<PVDChecklistModel>)!
                                group.leave()
                                semaphore.signal()
                            }, errorBlock: { (code, error) -> Void in DBManager.shared.setUpoadingFlag(checklistImage_table_name,keyId: imageModel.dbId!, flag: "0")
                                group.leave()
                                semaphore.signal()
                            })
                            semaphore.wait()
                            checklistVM.uploadChecklistImage(pvdId: self.model.id,checklistModel: checklistModel,imageModel: imageModel,operFlag: "ADD")
                        }
                    }
                    //2.local deleted image from server
                    let localDeletedImages = checklistModel.localDeletedImages
                    for imageModel in localDeletedImages {
                        group.enter()
                        DBManager.shared.setUpoadingFlag(checklistImage_table_name,keyId: checklistModel.dbId!, flag: "1")
                        
                        GlobalOperationQueue.addOperation {
                            let checklistVM = PVDDetailViewModel()
                            checklistVM.setBlockAfterNetwork({ (result) -> Void in
                                
                                DBManager.shared.deleteChecklistImageData(model: imageModel)
                                
                                self.model.pvd_checklists = (JSONDeserializer<PVDChecklistModel>.deserializeModelArrayFrom(json: result as? String) as? Array<PVDChecklistModel>)!
                                group.leave()
                                
                            }) { (code, error) -> Void in
                                DBManager.shared.setUpoadingFlag(checklistImage_table_name,keyId: imageModel.dbId!, flag: "0")
                                group.leave()
                            }
                            
                            checklistVM.uploadChecklistImage(pvdId: self.model.id, checklistModel: checklistModel,imageModel: imageModel,operFlag: "DEL")
                        }
                    }
                }else  {//text and boolean
                    
                    group.enter()
                    DBManager.shared.setUpoadingFlag(checklist_table_name,keyId: checklistModel.dbId!, flag: "1")
                    GlobalOperationQueue.addOperation {
                        let checklistVM = PVDDetailViewModel()
                        
                        checklistVM.setBlockAfterNetwork({ (result) -> Void in
                            DBManager.shared.deleteChecklsitData(pvdId: self.model.id,checklistId: checklistModel.id!)
                            
                            self.model.pvd_checklists = (JSONDeserializer<PVDChecklistModel>.deserializeModelArrayFrom(json: result as? String) as? Array<PVDChecklistModel>)!
                            group.leave()
                            
                        }, errorBlock: { (code, error) -> Void in
                            DBManager.shared.setUpoadingFlag(checklist_table_name,keyId: checklistModel.dbId!, flag: "0")
                            group.leave()
                            
                        })
                        
                        checklistVM.uploadChecklistDataWithoutImages(self.model,checklistId: checklistModel.id!)
                    }
                }
            }
            group.notify(queue: DispatchQueue.main) {
                self.cacheLoadData()
            }
        }
    }
    //异步上传Signature
    func uploadSignaturesAsync(){
        if !Connectivity.isConnectedToInternet{
            //检查是否有本地数据，有的话显示Reupload btn
            self.checkLocalInfoToSetReuploadInfo()
            return
        }
        if model.signaturesModifyFlag {
            //隐藏Detail的ReuploadView
            self.hideReuploadView()
            InstallationSignatureService().setDataInfo(self, model: self.model).uploadSignatures { [weak self] in
                guard let strongSelf = self else { return }
                strongSelf.cacheLoadData()
            }
        }
    }
    func getDetailBeforePanelInstalled(){
        //0.在panel install校验前，如果有网络就先拉下网络数据，否则无网直接panel installed
        if Connectivity.isConnectedToInternet {//有网路的处理步骤
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                Tool.shared.hideLoadingView()
                
                let oldSPVCheck: Bool? = self.model.spv_check
                if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                    self.model.copyAllValuesOfModel(data)
                }
                self.detailView.setData(model: self.model)
                //检查是否有本地数据，有的话显示Reupload btn
                self.checkLocalInfoToSetReuploadInfo()
                //校验spv状态是否从abled变成disabled
                if let oldCheck = oldSPVCheck, let newCheck = self.model.spv_check, oldCheck && !newCheck {
                    
                    let alertViewController = UIAlertController(title: "", message: "The retailer has disabled SPV verification for the current job.", preferredStyle: UIAlertController.Style.alert)
                    
                    let okAction = UIAlertAction(title: "OK", style: .cancel) { [unowned self](action) -> Void in
                        
                        //要刷新整个表格，因为Checklist Group 布局要刷新required和optional的完成数量
                        self.checkListView.tableView.refreshData(self.model)
                    }
                    alertViewController.addAction(okAction)
                    self.present(alertViewController, animated: true, completion: nil)
                }else{
                    if let spvInstalled = self.model.spv_installed, spvInstalled{//如果已经spv installed了，就刷新checklist数据
                        //要刷新整个表格，因为Checklist Group 布局要刷新required和optional的完成数量
                        self.checkListView.tableView.refreshData(self.model)
                    }else{
                        self.showPanelInstallAlertVC()
                    }
                    
                }
                
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.showPanelInstallAlertVC()
            }
            //add Loading view
            Tool.shared.showLoadingView("Checking...")
            vm.getInstallationsDetail()
            
        }else{
            self.showPanelInstallAlertVC()
        }
    }
    func showPanelInstallAlertVC(){
        //
        let vc = PanelInstallAlertViewController()
        vc.delegate = self
        vc.model = self.model
        if let date = UserDefaults.standard.object(forKey: self.panelInstalledDateOfCompletionKey) as? String {
            vc.cacheDateOfCompletion = date
        }
        self.navigationController?.pushViewController(vc, animated: false)
    }
    func checkSPVPanelInstalled(){
        //缓存date of completion时间
        if self.panelInstalledDateOfCompletion != "" {
            UserDefaults.standard.set(self.panelInstalledDateOfCompletion, forKey: self.panelInstalledDateOfCompletionKey)
        }
        //1.检查是否有invalid 的panel number
        for panelModel in self.model.pvd_serial_numbers {
            if panelModel.spv_status?.lowercased() == "invalid" && panelModel.modifyFlag == false {
                self.alertViewWithMsg(message: "Invalid panel serial number. Please confirm and try again.")
                return
            }
        }
        //2.panel number数量是否匹配
        let scannedPanelNumberCnt: String = "\(self.model.pvd_serial_numbers.count + self.model.localPVDSerialNumbers.count)"
        
        var planPanelNumberCnt = "0"
        if let systemDetail = self.model.system_detail, let data = systemDetail.number_panels{
            planPanelNumberCnt = data
        }
        if planPanelNumberCnt != scannedPanelNumberCnt {
            
            self.alertViewWithMsg(message: "The actual number of panels installed do not match with the original quantity.\n\nPanel quantity : " + planPanelNumberCnt + "\nPanel serial numbers: " + scannedPanelNumberCnt)
            return
        }
        //3.1 服务器上的panel number图片是否为空
        for panelModel in self.model.pvd_serial_numbers {
            if panelModel.image == nil || panelModel.image == "" {
                self.alertViewWithMsg(message: "Please upload a valid photo of the panel's serial number.")
                return
            }
        }
        //3.2 本地的panel number图片是否为空
        for panelModel in self.model.localPVDSerialNumbers {
            if panelModel.image == nil || panelModel.image == "" {
                self.alertViewWithMsg(message: "Please upload a valid photo of the panel's serial number.")
                return
            }
        }
        //4.是否有网络
        if Connectivity.isConnectedToInternet {//有网路时，获取最新的detail信息
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                Tool.shared.hideLoadingView()
                
                let oldSPVCheck: Bool? = self.model.spv_check
                if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                    self.model.copyAllValuesOfModel(data)
                }
                self.detailView.setData(model: self.model)
                //检查是否有本地数据，有的话显示Reupload btn
                self.checkLocalInfoToSetReuploadInfo()
                //5 校验spv状态是否从abled变成disabled
                if let oldCheck = oldSPVCheck, let newCheck = self.model.spv_check, oldCheck && !newCheck {
                    
                    let alertViewController = UIAlertController(title: "", message: "The retailer has disabled SPV verification for the current job.", preferredStyle: UIAlertController.Style.alert)
                    
                    let okAction = UIAlertAction(title: "OK", style: .cancel) { [unowned self](action) -> Void in
                        //要刷新整个表格，因为Checklist Group 布局要刷新required和optional的完成数量
                        self.checkListView.tableView.refreshData(self.model)
                    }
                    alertViewController.addAction(okAction)
                    self.present(alertViewController, animated: true, completion: nil)
                }
                //6. panel numbers，Installation address and date of completion，是否有本地数据或者
                //                if self.model.panelNumbersModifyFlag || self.model.detailModifyFlag {
                if self.model.panelNumbersModifyFlag || self.model.checkListModifyFlag{
                    self.alertViewWithUpload(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.localpanelnumbers.check.tip", comment: ""),toContinueType: "2")//"2": continue panel installed
                    return
                }
                //7,8
                self.checkSPVPanelInstalledAfterUploadLocalData()
                
            }){ (code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.checkSPVPanelInstalledCommonOther()
            }
            //add Loading view
            Tool.shared.showLoadingView("Checking...")
            vm.getInstallationsDetail()
            
        }else{//无网路的处理步骤
            self.checkSPVPanelInstalledCommonOther()
        }
        
    }
    func checkSPVPanelInstalledAfterUploadLocalData(){
        //7.是否验证了所有的panel numer
        for panelModel in self.model.pvd_serial_numbers{
            if let spvStatus = panelModel.spv_status {
                if spvStatus.lowercased() == "verifying" || spvStatus.lowercased() == "unverified" {
                    self.alertViewWithMsg(message: "The previous panel is still being verified. Please try again later.")
                    return
                }
            }
        }
        //8.Job是否有地址
        let installationAddress = self.model.install_address?.installation_address
        if installationAddress == nil || installationAddress == "" {
            self.alertViewWithMsg(message: "The current job is missing address information, please contact the retailer to fill out and try again.")
            return
        }
        //
        self.checkSPVPanelInstalledCommonOther()
    }
    func checkSPVPanelInstalledCommonOther(){
        //9.Installation address的经纬度是否为空
        guard let installAddress = self.model.install_address else {
            return
        }
        let installationLocation = installAddress.location
        if installationLocation == nil || installationLocation?.longitude == nil || installationLocation?.latitude == nil {
            self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.panalNumbers.spv.gps.notlocated", comment: ""))
            return
        }
        //10.是否存储了上次Panel Installed的离线经纬度
        //上次存储了定位位置
        if let latitudeValue = UserDefaults.standard.object(forKey: self.panelInstalledLatitudeKey) as? Double, let longitudeValue = UserDefaults.standard.object(forKey: self.panelInstalledLongitudeKey) as? Double {
            self.devationLocation.latitude = latitudeValue
            self.devationLocation.longitude = longitudeValue
            self.panelInstallValidateAPI()
        }else{//上次没有存储定位位置
            //11：location 定位是否开启
            let status  = CLLocationManager.authorizationStatus()
            if let spvCheck = self.model.spv_check, spvCheck {
                if status == .denied || status == .restricted {
                    let alert = UIAlertController(title: NSLocalizedString("pvd.detail.panalNumbers.locationservice.tip.title", comment: ""), message: NSLocalizedString("pvd.detail.panalNumbers.locationservice.tip.content", comment: ""), preferredStyle: .alert)
                    
                    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
                    let settingAction = UIAlertAction(title: "Settings", style: UIAlertAction.Style.default) { (_) in
                        
                        if  UIApplication.shared.canOpenURL(URL(string: UIApplication.openSettingsURLString)!) {
                            UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
                        }
                    }
                    
                    alert.addAction(cancelAction)
                    alert.addAction(settingAction)
                    
                    present(alert, animated: true, completion: nil)
                    
                }
            }
            //12.能否定位GPS/网络
            self.devationLocation.latitude = nil
            self.devationLocation.longitude = nil
            //
            self.panelInstalledLcation.latitude = nil
            self.panelInstalledLcation.longitude = nil
            
            LocationManager.shared.subscription(.single).fetchWithCompletion {[weak self](location, error) in
                guard let strongSelf = self else {
                    return
                }
                if location != nil {
                    var currentLocation: CLLocation = location!
                    if Tool.shared.isLocationOutOfChina(location!.coordinate) == false{
                        let gcj02Coordinate = YJLocationConverter.yj_WGS84Convert(toGCJ02: location!.coordinate)
                        currentLocation = CLLocation(latitude: gcj02Coordinate.latitude, longitude: gcj02Coordinate.longitude)
                    }
                    
                    //获取安装位置的经纬度
                    if let installedAddress = strongSelf.model.install_address,let installedLocation = installedAddress.location {
                        if let latitude = installedLocation.latitude, let longitude = installedLocation.longitude {
                            let installedLocation = CLLocation(latitude: latitude, longitude: longitude)
                            
                            //单位是m
                            let distanceFromCurrentLocation = currentLocation.distance(from: installedLocation)
                            
                            //13.当前位置是否在owner 安装地址范围内：不在范围内
                            if let devationSetting = strongSelf.model.installation_position_deviation, distanceFromCurrentLocation > devationSetting{
                                
                                //14.扫描位置是否在安装范围内
                                for panelModel in strongSelf.model.pvd_serial_numbers {
                                    if let latitide = panelModel.latitude, let longitude = panelModel.longitude {
                                        let panelInstalledLocation = CLLocation(latitude: latitide, longitude: longitude)
                                        
                                        let distance = installedLocation.distance(from: panelInstalledLocation)
                                        //获取系统设置的最小距离的值（单位：米）
                                        if let devationSetting = strongSelf.model.installation_position_deviation, distance <= devationSetting{
                                            
                                            strongSelf.devationLocation.latitude = panelInstalledLocation.coordinate.latitude
                                            strongSelf.devationLocation.longitude = panelInstalledLocation.coordinate.longitude
                                            break
                                        }
                                    }
                                }
                                if strongSelf.devationLocation.latitude == nil && strongSelf.devationLocation.longitude == nil {
                                    strongSelf.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.installaddress.check.tip", comment: ""))
                                }else{//在panel number中存在范围内的经纬度，提示用s户是否使用panel number中的位置
                                    let alertViewController = UIAlertController(title: "", message: NSLocalizedString("pvd.detail.checklist.panelinstalled.usescanningaddress.tip.two", comment: ""), preferredStyle: UIAlertController.Style.alert)
                                    
                                    let okAction = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
                                        strongSelf.panelInstallValidateAPI()
                                    }
                                    let noAction = UIAlertAction(title: "No", style: .cancel,handler: nil)
                                    
                                    alertViewController.addAction(okAction)
                                    alertViewController.addAction(noAction)
                                    strongSelf.present(alertViewController, animated: true, completion: nil)
                                    
                                }
                            }else{//当前位置是否在owner 安装地址范围内：在范围内
                                strongSelf.panelInstalledLcation.latitude = currentLocation.coordinate.latitude
                                strongSelf.panelInstalledLcation.longitude = currentLocation.coordinate.longitude
                                
                                strongSelf.devationLocation.latitude = currentLocation.coordinate.latitude
                                strongSelf.devationLocation.longitude = currentLocation.coordinate.longitude
                                strongSelf.panelInstallValidateAPI()
                            }
                        }else{
                            
                            strongSelf.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.installaddress.required.tip", comment: ""))
                            return
                        }
                    }
                }else{//定位失败
                    if let installedAddress = strongSelf.model.install_address,let installedLocation = installedAddress.location {
                        if let latitude = installedLocation.latitude, let longitude = installedLocation.longitude {
                            let installedLocation = CLLocation(latitude: latitude, longitude: longitude)
                            //14.扫描位置是否在安装范围内
                            for panelModel in strongSelf.model.pvd_serial_numbers {
                                if let latitide = panelModel.latitude, let longitude = panelModel.longitude {
                                    let panelInstalledLocation = CLLocation(latitude: latitide, longitude: longitude)
                                    
                                    let distance = installedLocation.distance(from: panelInstalledLocation)
                                    //获取系统设置的最小距离的值（单位：米）
                                    if let devationSetting = strongSelf.model.installation_position_deviation, distance <= devationSetting{
                                        
                                        strongSelf.devationLocation.latitude = panelInstalledLocation.coordinate.latitude
                                        strongSelf.devationLocation.longitude = panelInstalledLocation.coordinate.longitude
                                        break
                                    }
                                }
                            }
                            if strongSelf.devationLocation.latitude == nil && strongSelf.devationLocation.longitude == nil {
                                strongSelf.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.availableaddress.check.tip", comment: ""))
                            }else{//在panel number中存在范围内的经纬度，提示用户是否使用panel number中的位置
                                let alertViewController = UIAlertController(title: "", message: NSLocalizedString("pvd.detail.checklist.panelinstalled.usescanningaddress.tip", comment: ""), preferredStyle: UIAlertController.Style.alert)
                                
                                let okAction = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
                                    strongSelf.panelInstallValidateAPI()
                                }
                                let noAction = UIAlertAction(title: "No", style: .cancel,handler: nil)
                                
                                alertViewController.addAction(okAction)
                                alertViewController.addAction(noAction)
                                strongSelf.present(alertViewController, animated: true, completion: nil)
                                
                            }
                        }
                    }
                    
                }
            }
        }
    }
    
    func panelInstallValidateAPI()
    {
        //15.有网络直接调用panel installe的 api
        if Connectivity.isConnectedToInternet {
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                Tool.shared.hideLoadingView()
                //请求成功后，删除保存的经纬度
                UserDefaults.standard.removeObject(forKey: self.panelInstalledLatitudeKey)
                UserDefaults.standard.removeObject(forKey: self.panelInstalledLongitudeKey)
                UserDefaults.standard.removeObject(forKey: self.panelInstalledDateOfCompletionKey)
                //缓存数据，并设置panel instealled为true
                self.loadData(true,checkIfNeedResignFlag: true)
                
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                if error == RequestErrorType.NetworkError.rawValue{
                    if let latitude = self.panelInstalledLcation.latitude, let longitude = self.panelInstalledLcation.longitude {
                        UserDefaults.standard.set(latitude, forKey: self.panelInstalledLatitudeKey)
                        UserDefaults.standard.set(longitude, forKey: self.panelInstalledLongitudeKey)
                        
                        //            Tool.shared.showToast(msg: "Save cache address\nlatitude: \(self.devationLocation.latitude)" + "\nlongitude:\(self.devationLocation.longitude)", parentView: self.checkListView)
                        self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.getcurrentlocation.withoutnetwork", comment: ""))
                    }else{//使用的是扫描panel number时地址
                        self.alertViewWithMsg(message: "We can't verify your data due to network failure. Please try again later.")
                        
                    }
                }else{
                    self.showErrorInfo(code, error)
                }
            }
            //add Loading view
            Tool.shared.showLoadingView("Checking...")
            vm.panelInstalledValidate(self.devationLocation,dateOfCompletion: self.panelInstalledDateOfCompletion)
        }else{
            
            //没有网络，保存panel installed的经纬度
            if let latitude = self.panelInstalledLcation.latitude, let longitude = self.panelInstalledLcation.longitude {
                UserDefaults.standard.set(latitude, forKey: self.panelInstalledLatitudeKey)
                UserDefaults.standard.set(longitude, forKey: self.panelInstalledLongitudeKey)
                //            Tool.shared.showToast(msg: "Save cache address\nlatitude: \(self.devationLocation.latitude)" + "\nlongitude:\(self.devationLocation.longitude)", parentView: self.checkListView)
                self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.getcurrentlocation.withoutnetwork", comment: ""))
            }else{//使用的是扫描panel number时地址
                self.alertViewWithMsg(message: "We can't verify your data due to network failure. Please try again later.")
                
            }
        }
        
    }
    func toClickBoolItemOfChecklist(_ serverModel: PVDChecklistModel, index: IndexPath){
        guard let _ = serverModel.id, let _ = APPConfig.loginInfo.currentPVDId else {
            return
        }
        let localChecklist = DBManager.shared.loadChecklistDataByChecklistId(pvdId: APPConfig.loginInfo.currentPVDId!, checklistId: serverModel.id!)
        self.currentCheckListModel.pvdId = APPConfig.loginInfo.currentPVDId
        self.currentCheckListModel.id = serverModel.id
        self.currentCheckListModel.is_required = serverModel.is_required
        self.currentCheckListModel.type = serverModel.type
        self.currentCheckListModel.full_name = APPConfig.loginInfo.fullName
        self.currentCheckListModel.title = serverModel.title
        //1.local data exist
        if localChecklist.dbId != nil {
            if localChecklist.answer == "true" {
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.answer = ""
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.full_name = ""
            }else{
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.answer = "true"
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.full_name = APPConfig.loginInfo.fullName
            }
        }else{
            if serverModel.answer == "true" {
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.answer = ""
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.full_name = ""
                
            }else{
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.answer = "true"
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.full_name = APPConfig.loginInfo.fullName
                
            }
        }
        DBManager.shared.insertChecklistData(model: self.currentCheckListModel)
        InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
        //要刷新整个表格，因为Checklist Group 布局要刷新required和optional的完成数量
        self.checkListView.tableView.refreshData(self.model)//reloadRows(at: [index], with: UITableView.RowAnimation.none)
        self.uploadCheckListWithoutImage(index)
    }
    //监听Contensize是获取Tableview 高度最准确的方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?){
        guard let tableView = object as? UITableView else { return  }
        if keyPath == "contentSize" {
            if let value = change?[.newKey]{
                if let size  = value as? CGSize{
                    if tableView == self.checkListView.tableView{
                        self.checkListView.tableViewHeightConstraint?.update(offset: size.height)
                    }else if tableView == self.detailView.attachmentView.tableView{
                        self.detailView.attachmentView.tableViewHeightConstraint?.update(offset: size.height)
                    }else if tableView == self.detailView.panelInfoView.tableView{
                        self.detailView.panelInfoView.tableViewHeightConstraint?.update(offset: size.height)
                    }else if tableView == self.detailView.inverterInfoView.tableView{
                        self.detailView.inverterInfoView.tableViewHeightConstraint?.update(offset: size.height)
                    }else if tableView == self.detailView.batteryInfoView.tableView{
                        self.detailView.batteryInfoView.tableViewHeightConstraint?.update(offset: size.height)
                    }
                }
            }
        }
    }
    
    deinit {
        //contentSize的removeObserver必须放在这里，因为上传checklist，panelnumber，signature等数据时，会实时刷新这两个tableview，就会触发contentSize的观察，如果快速返回到installation list中时，正好在reloaddata这连个表格，就会导致crash，因为此VC已经释放
        if self.isViewDidLoad{
            self.checkListView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.detailView.attachmentView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.detailView.panelInfoView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.detailView.inverterInfoView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.detailView.batteryInfoView.tableView.removeObserver(self, forKeyPath: "contentSize")
        }
    }
    override func viewDidLayoutSubviews() {
        super.updateViewConstraints()
        self.detailView.attachmentView.tableView.separatorStyle = .none
        self.checkListView.tableView.separatorStyle = .none//因为设置在View中不管用，所以设置在这里
        self.signatureView.signatureListView.separatorStyle = .none
        self.detailView.panelInfoView.tableView.separatorStyle = .none
        self.detailView.inverterInfoView.tableView.separatorStyle = .none
        self.detailView.batteryInfoView.tableView.separatorStyle = .none
    }
    override func backToPre() {
        super.backToPre()
        Tool.shared.cancelAllNetworkRequestForPVD()
        self.delegate?.refreshReuploadInfo()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        Tool.shared.printDebug("\(self) didReceiveMemoryWarning")
    }
}
extension InstallationDetailViewController: UIDocumentPickerDelegate {
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        guard let firstUrl = urls.first else {return}
        let urlAuthrized = firstUrl.startAccessingSecurityScopedResource()
        //获取授权
        if urlAuthrized {
            self.alertViewWithMsg(message: "授权成功")
        }else{
            self.alertViewWithMsg(message: "授权失败")
        }
    }
}
extension InstallationDetailViewController: ReloadDataForDeleteInverterNumberDelegate,ReloadDataForDeletePanelNumberDelegate{
    //ReloadDataForDeleteInverterNumberDelegate
    func reloadDataForDeleteInverterNumber(){
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
        //4.inverter numbers
        self.checkListView.tableView.reloadData()
        self.checkJobMsg()
    }
    //ReloadDataForDeletePanelNumberDelegate
    //直接用self.model = PVDDetailModel.deserialize(from: result as? NSDictionary)，不影响删除时的数据源，因为tableview在deleterow之前已经处理过数据源了，否则如果用reloadData方法在弱网的情况下数据源会混乱，deleterows容易报错
    func reloadDataForDeletePanelNumber(){
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
        //3.panel numbers
        self.checkListView.tableView.reloadData()
        self.checkJobMsg()
    }
}
 extension InstallationDetailViewController:RefreshChecklistDelegate,SignatureViewDelegate,ReloadDataDelegate,RefreshPVDDetailChecklistDelegate,PanelInstallDelegate,JobErrorMsgDelegate,HideDetailReuploadViewDelegate {
    //HideDetailReuploadViewDelegate
    func hideDetailReuploadView() {
        self.hideReuploadView()
    }
    //JobErrorMsgDelegate
    func recheckJobMsg() {
        self.getLocalErrorHistory()
        self.checkJobMsg()
    }
    //
    func toPanelInstall(_ dateStr: String) {
        self.panelInstalledDateOfCompletion = dateStr
        self.checkSPVPanelInstalled()
    }
    //ReloadDataDelegate
    func reloadData() {
        self.loadData(true)
    }
    //RefreshPVDDetailChecklistDelegate
    func refreshPVDDetailChecklist() {
        InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
        self.checkListView.tableView.refreshData(self.model)
    }
    func checkIfHaveReuploadInfo(){
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
    }
    fileprivate func showEditCheckListText(_ serverModel: PVDChecklistModel){
        
        let vc = InstallationEditChecklistTextViewController()
        vc.model = self.model
        vc.serverModel = serverModel
        vc.cacheDelegate = self
        vc.delegate = self
        vc.modalPresentationStyle = .overFullScreen
        self.present(vc, animated: true, completion: nil)
    }
    //RefreshChecklistDelegate
    func refreshChecklist(){
        InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
        self.checkListView.tableView.refreshData(self.model)
        self.uploadCheckListAsync()
    }
    //SignatureViewDelegate
    func refreshSignatureList() {
        self.refreshSignatureListForLocalData()
        self.uploadSignaturesAsync()
    }
    //获取本地数据，刷新签名列表
    func refreshSignatureListForLocalData() {
        InstallationDetailVCHelper.shared().getLocalSignatures(self.model)
        self.signatureView.signatureListView.setData(self.model)
    }
}
extension InstallationDetailViewController: PHPickerViewControllerDelegate{
    @available(iOS 14, *)
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true) {//代码必需加到回调中，防止选图片界面dismiss反应慢，导致Add可以点击多次导致增加n多图片
            let itemProviders = results.map(\.itemProvider)
            guard itemProviders.count > 0 else {
                return
            }
            for (_ , itemProvider) in itemProviders.enumerated() where itemProvider.canLoadObject(ofClass: UIImage.self) {
                itemProvider.loadObject(ofClass: UIImage.self) {[weak self] (image, error) in
                    DispatchQueue.main.async {
                        if let strongSelf = self, let resultImage = image as? UIImage{
                            strongSelf.uploadAttachment(resultImage)
                        }
                    }
                }
            }
        }
        
    }
}
